#! /usr/bin/env python

# Get usage information from your ISP.

# Copyright (c) 2008-2012 Peter Scully <peter@peterscully.name> and licenced under the GNU General Public License version 3.


import sys
import logging
import urllib2
from bs4 import BeautifulSoup

def Internode(username, password):
    # Constants
    baseurl = "https://customer-webtools-api.internode.on.net"
    apiloc = "/api/v1.5/"

    # Initial Values
    metered = "NaN"
    unmetered = "NaN"
    total = "NaN"
    quota = "NaN"
    uploads = "NaN"

    # Setup Connection
    passman = urllib2.HTTPPasswordMgrWithDefaultRealm()
    passman.add_password(None, baseurl + apiloc, username, password)
    authhandler = urllib2.HTTPBasicAuthHandler(passman)
    opener = urllib2.build_opener(authhandler)
    opener.addheaders = [('User-agent', useragent)]
    urllib2.install_opener(opener)

    # Get ServiceID
    servicedata = urllib2.urlopen(baseurl + apiloc)
    soup = BeautifulSoup(servicedata.read())
    logging.debug("servicedata:\n" + soup.prettify())
    serviceloc = soup.internode.api.services.service["href"] # TODO: Internode's API supports multiple services; I'm only using the first one.  What will happen if I get multiple?
    logging.debug("serviceloc:" + serviceloc)

    # Get Service Info
    servicelist = urllib2.urlopen(baseurl + serviceloc)
    soup = BeautifulSoup(servicelist.read())
    for resource in soup.internode.api.resources:
        logging.debug("resource:\n" + resource.prettify())
        if resource.contents[0] == "usage":
            usageloc = resource["href"]
            logging.debug("usageloc: " + usageloc)
            break

    # Get Usage Data
    trafficdata = urllib2.urlopen(baseurl + usageloc)
    soup = BeautifulSoup(trafficdata.read())
    logging.debug("trafficdata:\n" + soup.prettify())

    for item in soup.internode.api:
        if item.name == "traffic":
            logging.debug("Traffic:\n" + item.prettify())
            if item["name"] == "total":
                total = str(int(item.contents[0]) / 1000000)
                quota = str(int(item["quota"]) / 1000000)
            elif item["name"] == "metered":
                metered = str(int(item.contents[0]) / 1000000)
            elif item["name"] == "unmetered":
                unmetered = str(int(item.contents[0]) / 1000000)

    logging.info("metered: " + metered)
    logging.info("unmetered: " + unmetered)
    logging.info("total: " + total)
    logging.info("quota: " + quota)
    logging.info("uploads: " + uploads)

    # Temporary fix for values not yet returned by the Internode API v1.5
    if metered == "NaN":
        metered = total
    if unmetered == "NaN":
        unmetered = "0"

    return [metered, quota, unmetered, uploads]

########
# MAIN #
########

# Set up debug level (default level is WARNING)
logging.basicConfig(level=logging.WARNING)

# Constants
useragent = "CactiISPQuota/1.01 (beta-1)"
config_file = "/etc/cacti/ISP_Quota.conf"

# Default values
isp_name = "[Unknown]"
username = "[Unknown]"
password = "[Unknown]"
usage = "NaN"
quota = "NaN"
unmetered = "NaN"
uploads = "NaN"

# Get arguements
try:
    isp_index = sys.argv[1]
except IndexError:
    sys.exit("Usage: get-isp-quota isp_index")

# Pull isp_name, username & password from config file
try:
    f = open(config_file)
    for line in f:
        data = line.split()
        if len(data) > 0 and data[0] == isp_index:
            isp_name = data[1].lower()
            username = data[2]
            password = data[3]
            break
    f.close()
except IOError:
    sys.exit("Error opening config file: " + config_file)

if isp_name == "[Unknown]":
    logging.error("Can't find '" + isp_index + "' in " + config_file)
else:
    logging.debug("username: " + username)
    logging.debug("password: [HIDDEN]") # + password
    logging.debug("isp_name: " + isp_name)

# Calculate usage
if isp_name == "internode":
    usage, quota, unmetered, uploads = Internode(username, password)
else:
    logging.error("Unknown/Unimplemented ISP: " + isp_name)

print "usage:" + usage, "limit:" + quota, "unmetered:" + unmetered, "uploads:" + uploads
